# -*- coding: utf-8 -*-
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#作者：cacho_37967865
#博客：https://blog.csdn.net/sinat_37967865
#文件：cryptography_model.py
#日期：2023-12-28
#备注：生成证书 
pip install cryptography
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID, ExtensionOID
from cryptography.hazmat.primitives import serialization
import datetime

# 生成RSA密钥对
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
    backend=default_backend()
)

# 创建证书构建器
builder = x509.CertificateBuilder()

# 设置证书的主题和颁发者
builder = builder.subject_name(x509.Name([
    x509.NameAttribute(NameOID.COMMON_NAME, u'PSD2'),
    x509.NameAttribute(NameOID.COUNTRY_NAME, u'GB'),
    x509.NameAttribute(NameOID.STREET_ADDRESS, u'London'),
    x509.NameAttribute(NameOID.JURISDICTION_LOCALITY_NAME, u'PSD2XX-TEST-0000001'),
    ]))

builder = builder.issuer_name(x509.Name([
    x509.NameAttribute(NameOID.COMMON_NAME, 'PSD2'),
]))

# 设置证书的有效期
builder = builder.not_valid_before(datetime.datetime.today() - datetime.timedelta(days=1))
builder = builder.not_valid_after(datetime.datetime.today() + datetime.timedelta(days=365))

# 生成新的serial number
new_serial_number = x509.random_serial_number()
builder = builder.serial_number(new_serial_number)

# 设置证书的公钥
builder = builder.public_key(private_key.public_key())

qc_statement = x509.UnrecognizedExtension(ExtensionOID.QC_Statement, b'test')
builder = builder.add_extension(qc_statement, critical=True)

# 添加x509扩展
builder = builder.add_extension(
    x509.SubjectAlternativeName([x509.DNSName(u'localhost')]),
    critical=True,
)

# 签署证书
certificate = builder.sign(
    private_key=private_key, algorithm=hashes.SHA256(),
    backend=default_backend()
)

# 打印证书信息
print(certificate)

# 将新证书保存到文件
with open("H:\wei\OpenSSL-Win64\\bin\cert.crt", "wb") as new_cert_file:
    new_cert_file.write(certificate.public_bytes(serialization.Encoding.PEM))